'''
计算高德 api 骑行路径，输入坐标为地球坐标，转为火星
需确保起点与终点坐标分别在原始文件的第 3 和第 5 列，如不在，需修改相应列数，见 get_path 函数注释
2019-8-7
'''


import requests
import random
import multiprocessing
import math
import urllib
import urllib.request
import json



API_KEY_1 = "f20cecc669c317e1a7eb12a967b0dd24"
API_KEY_2 = "09ec2260405e3c4749c651a416042a51"
API_KEY_3 = "fec9ee72f749032ebb2f8f6cb91418b6"
API_KEY_4 = "de90008c178ecf5efe520d24a750361c"
API_KEY_5 = "46a533017040f22359d642bae067ed94"
API_KEY_6 = "84e5b92c3e8d300d3af5a073c78d686c"
API_KEY_7 = "eb55f5c2995d43474d52e34fc558268f"
API_KEY_8 = "5aee410fd9c8788004c563c7cbf337ee"
API_KEY_9 = "8125e85990196277fd87d28f5683d337"
API_KEY_10 = "8009a591bd49300a213ad36204068442"
API_KEY_11 = "1eee488dae50241de01123e64c45e6c2"
API_KEY_12 = "c2597e916c510998331e5091455281b7"
API_KEY_13 = "74159ff7e4fdc088f4cb66ce1867f0fd"
API_KEY_14 = "4efdd197e6e84075ec28ef5c312c25c7"
API_KEY_15 = "0294c63ad116dcc98f2ed317b3ddab44"
API_KEY_16 = "8870198fcbdb87cfe0bf91f51562e99e"
API_KEY_17 = "25799a23cd6be36ef6c9207e6f30d5b7"
API_KEY_18 = "91630c26e23dca191ff4a416fa8749ca"
API_KEY_19 = "9a502e0cfa7df1dd67f1c7091152eba4"
API_KEY_20 = "3ca6b5ee42072425b9e77a744528bda7"
API_KEY_LIST = ["f20cecc669c317e1a7eb12a967b0dd24","09ec2260405e3c4749c651a416042a51","fec9ee72f749032ebb2f8f6cb91418b6","de90008c178ecf5efe520d24a750361c","46a533017040f22359d642bae067ed94"
               ,"84e5b92c3e8d300d3af5a073c78d686c","eb55f5c2995d43474d52e34fc558268f","5aee410fd9c8788004c563c7cbf337ee","8009a591bd49300a213ad36204068442"]

'''
修改读写地址及查询城市
'''
file_write_obj = open("D:/提数据/190807-自行车专用路内参/data/biking_result00.txt", 'a', encoding="utf-8")
file_read_obj = open("D:/提数据/190807-自行车专用路内参/data/1908-huitiantown_left/part-00000", "r", encoding="utf-8")
# file_write_obj = open("/Users/weiwenzhao/Desktop/biking_result00", 'a', encoding="utf-8")
# file_read_obj = open("/Users/weiwenzhao/Desktop/part-00000", "r", encoding="utf-8")
city = '北京'


x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626  # π
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 扁率


class Geocoding:
    def __init__(self, api_key):
        self.api_key = api_key

    def geocode(self, address):
        """
        利用高德geocoding服务解析地址获取位置坐标
        :param address:需要解析的地址
        :return:
        """
        geocoding = {'s': 'rsv3',
                     'key': self.api_key,
                     'city': '全国',
                     'address': address}
        geocoding = urllib.parse.urlencode(geocoding)
        ret = urllib.request.urlopen("%s?%s" % ("http://restapi.amap.com/v3/geocode/geo", geocoding))

        if ret.getcode() == 200:
            res = ret.read()
            json_obj = json.loads(res)
            if json_obj['status'] == '1' and int(json_obj['count']) >= 1:
                geocodes = json_obj['geocodes'][0]
                lng = float(geocodes.get('location').split(',')[0])
                lat = float(geocodes.get('location').split(',')[1])
                return [lng, lat]
            else:
                return None
        else:
            return None


def wgs84_to_gcj02(lng, lat):
    """
    WGS84转GCJ02(火星坐标系)
    :param lng:WGS84坐标系的经度
    :param lat:WGS84坐标系的纬度
    :return:
    """
    if out_of_china(lng, lat):  # 判断是否在国内
        return lng, lat
    dlat = _transformlat(lng - 105.0, lat - 35.0)
    dlng = _transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * pi
    magic = math.sin(radlat)
    magic = 1 - ee * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
    dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [mglng, mglat]


def _transformlat(lng, lat):
    ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
          0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lat * pi) + 40.0 *
            math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
            math.sin(lat * pi / 30.0)) * 2.0 / 3.0
    return ret


def _transformlng(lng, lat):
    ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
          0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lng * pi) + 40.0 *
            math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
            math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
    return ret


def out_of_china(lng, lat):
    """
    判断是否在国内，不在国内不做偏移
    :param lng:
    :param lat:
    :return:
    """
    return not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55)

def get_path(line): #获取骑行路径

    try:

        origin_location = line.split('\t')[3]   #起点坐标在原始文件的列数，第一列记为 0
        dest_location = line.split('\t')[5]     #终点坐标在原始文件的列数，第一列记为 0


        # 将地球坐标转为火星坐标
        origin_wgs = wgs84_to_gcj02(float(origin_location.split(',')[0]),float(origin_location.split(',')[1]))
        dest_wgs = wgs84_to_gcj02(float(dest_location.split(',')[0]), float(dest_location.split(',')[1]))
        origin_location_wgs = str(origin_wgs[0]) + ',' + str(origin_wgs[1])
        dest_location_wgs = str(dest_wgs[0]) + ',' + str(dest_wgs[1])

        #获取路径信息
        url = 'http://restapi.amap.com/v4/direction/bicycling?origin='+origin_location_wgs +'&destination='+dest_location_wgs+'&province='+city+'&output=json&key='+API_KEY_LIST[random.randint(0,19)]
        session = requests.session()
        result = session.get(url).json()

        if result['data'] != '':
            paths = result['data']['paths'] # 出行线路
            for path in paths:
                whole_distance = path['distance']
                duration = path['duration']
                steps = path['steps']

                # 判断是否在自行车专用路，添加相应标签
                if str(steps).find('自行车专用路') > 0:
                    biking_tag = '自行车专用路'
                else:
                    biking_tag = '其他道路'

                # count += 1
                path_line = line.replace('\n','') + str(origin_location_wgs) + "\t" + str(dest_location_wgs) + "\t" + str(whole_distance) + "\t" + str(duration) + "\t" + biking_tag + "\t" + str(steps)
                file_write_obj.write(path_line)
                file_write_obj.write('\n')
                # print(biking_tag)
                print('成功获取数据')
                # print(count)
        else:
            print(result)
            print('无数据')
    except Exception:  # 超出等待时间后，再次运行
        return get_path(line)

if __name__ == '__main__':

    count = 1
    pool = multiprocessing.Pool()
    reader = file_read_obj
    content = reader.readlines()
    reader.close()
    #多进程运行
    for line in content:
        pool.apply_async(get_path, (line,))
    pool.close()  # 关闭进程池，表示不能在往进程池中添加进程
    pool.join()  # 等待进程池中的所有进程执行完毕，必须在close()之后调用
    print("Sub-process(es) done.")






